home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / browse.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  9KB  |  429 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: browse.c,v 1.46 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <limits.h>
  10. #include "opennap.h"
  11. #include "debug.h"
  12.  
  13. #ifndef ROUTING_ONLY
  14.  
  15. typedef struct
  16. {
  17.     short   count;
  18.     short   max;
  19.     USER   *sender;
  20.     USER   *user;
  21. }
  22. BROWSE;
  23.  
  24. static void
  25. browse_callback (DATUM * info, BROWSE * ctx)
  26. {
  27.     /* avoid flooding the client */
  28.     if (ctx->max == 0 || ctx->count < ctx->max)
  29.     {
  30.     send_user (ctx->sender, MSG_SERVER_BROWSE_RESPONSE,
  31.            "%s \"%s\" %s %u %hu %hu %hu",
  32.            info->user->nick, info->filename,
  33. #if RESUME
  34.            info->hash,
  35. #else
  36.            "00000000000000000000000000000000",
  37. #endif
  38.            info->size,
  39.            BitRate[info->bitrate], SampleRate[info->frequency],
  40.            info->duration);
  41.  
  42.     ctx->count++;
  43.     }
  44. }
  45.  
  46. #endif /* ! ROUTING_ONLY */
  47.  
  48. /* 211 [ :<sender> ] <nick> [ <max> ]
  49.    browse a user's files */
  50. HANDLER (browse)
  51. {
  52.     USER   *sender, *user;
  53.     char   *nick;
  54.     int     result;
  55.  
  56.     (void) tag;
  57.     (void) len;
  58.     ASSERT (validate_connection (con));
  59.     if (pop_user (con, &pkt, &sender))
  60.     return;
  61.     nick = next_arg (&pkt);
  62.     if (!nick)
  63.     {
  64.     unparsable (con);
  65.     return;
  66.     }
  67.     if (invalid_nick (nick))
  68.     {
  69.     invalid_nick_msg (con);
  70.     return;
  71.     }
  72.     user = hash_lookup (Users, nick);
  73.     if (!user)
  74.     {
  75.     if (ISUSER (con))
  76.     {
  77.         /* the napster servers send a 210 instead of 404 for this case */
  78.         send_cmd (con, MSG_SERVER_USER_SIGNOFF, "%s", nick);
  79.         /* always terminate the list */
  80.         send_cmd (con, MSG_SERVER_BROWSE_END, "%s", nick);
  81.     }
  82.     return;
  83.     }
  84.     ASSERT (validate_user (user));
  85.  
  86.     if (pkt)
  87.     {
  88.     result = atoi (pkt);
  89.     if (Max_Browse_Result > 0 && result > Max_Browse_Result)
  90.         result = Max_Browse_Result;
  91.     }
  92.     else
  93.     result = Max_Browse_Result;
  94.  
  95.     if (!option (ON_REMOTE_BROWSE) &&
  96.         (!ISUSER (sender->con) || !ISUSER (user->con)))
  97.     {
  98.     /* remote browsing is not supported */
  99.     send_user (sender, MSG_SERVER_BROWSE_END, "%s %u",
  100.         user->nick, (user->shared > 0) ? user->ip : 0);
  101.     return;
  102.     }
  103.  
  104.     if (ISUSER (user->con))
  105.     {
  106. #ifndef ROUTING_ONLY
  107.     if (user->con->uopt->files)
  108.     {
  109.         BROWSE  data;
  110.  
  111.         data.count = 0;
  112.         data.user = user;
  113.         data.sender = sender;
  114.         data.max = pkt ? atoi (pkt) : 0;
  115.         if (Max_Browse_Result > 0 && data.max > Max_Browse_Result)
  116.         data.max = Max_Browse_Result;
  117.         hash_foreach (user->con->uopt->files,
  118.               (hash_callback_t) browse_callback, &data);
  119.     }
  120. #endif /* ! ROUTING_ONLY */
  121.     
  122.     /* send end of browse list message */
  123.     send_user (sender, MSG_SERVER_BROWSE_END, "%s %u", user->nick,
  124.            /* don't send the ip if the user isn't sharing - security */
  125.            user->shared > 0 ? user->ip : 0);
  126.     }
  127.     else
  128.     {
  129.     /* relay to the server that this user is connected to */
  130.     send_cmd (user->con, tag, ":%s %s %d", sender->nick, user->nick,
  131.           result);
  132.     }
  133. }
  134.  
  135. /* deprecated - clients should do direct browsing with 640 now.  this was
  136.  * causing too much cpu use for users with large amounts of shared files
  137.  */
  138. #if 0
  139. #ifndef ROUTING_ONLY
  140. static void
  141. create_file_list (DATUM * d, LIST ** p)
  142. {
  143.     DATUM  *f;
  144.  
  145.     while (*p)
  146.     {
  147.     f = (*p)->data;
  148.     if (strcasecmp (d->filename, f->filename) <= 0)
  149.     {
  150.         LIST   *n = CALLOC (1, sizeof (LIST));
  151.  
  152.         n->data = d;
  153.         n->next = *p;
  154.         *p = n;
  155.         return;
  156.     }
  157.     p = &(*p)->next;
  158.     }
  159.     *p = CALLOC (1, sizeof (LIST));
  160.     (*p)->data = d;
  161. }
  162.  
  163. static char *
  164. last_slash (char *s)
  165. {
  166.     /* const */ char *p;
  167.  
  168.     for (;;)
  169.     {
  170.     p = strpbrk (s + 1, "/\\");
  171.     if (!p)
  172.         return s;
  173.     s = p;
  174.     }
  175. }
  176.  
  177. static char *
  178. dirname (char *d, int dsize, /* const */ char *s)
  179. {
  180.     char   *p;
  181.  
  182.     strncpy (d, s, dsize - 1);
  183.     d[dsize - 1] = 0;
  184.     p = last_slash (d);
  185.     *p = 0;
  186.     return d;
  187. }
  188.  
  189. static char *
  190. my_basename (char *d, int dsize, /* const */ char *s)
  191. {
  192.     s = last_slash (s);
  193.     strncpy (d, s + 1, dsize - 1);
  194.     d[dsize - 1] = 0;
  195.     return d;
  196. }
  197. #endif /* ! ROUTING_ONLY */
  198.  
  199. /* 10301 [ :<sender> ] <nick>
  200.    new browse requst */
  201. HANDLER (browse_new)
  202. {
  203.     USER   *sender, *user;
  204.     char   *nick;
  205.     int     results = -1;
  206.  
  207.     (void) len;
  208.     ASSERT (validate_connection (con));
  209.     if (pop_user (con, &pkt, &sender))
  210.     return;
  211.     nick = next_arg (&pkt);
  212.     if (!nick)
  213.     {
  214.     unparsable (con);
  215.     return;
  216.     }
  217.     user = hash_lookup (Users, nick);
  218.     if (!user)
  219.     {
  220.     if (ISUSER (con))
  221.         send_cmd (con, MSG_SERVER_NOSUCH, "browse failed: no such user");
  222.     send_user (sender, tag, "%s 0", nick);    /* always terminate */
  223.     return;
  224.     }
  225.  
  226.     if (pkt)
  227.     {
  228.     results = atoi (pkt);
  229.     if (Max_Browse_Result > 0 && results > Max_Browse_Result)
  230.         results = Max_Browse_Result;
  231.     }
  232.     else
  233.     results = Max_Browse_Result;
  234.  
  235.     if (ISUSER (user->con))
  236.     {
  237. #ifndef ROUTING_ONLY
  238.     if (user->con->uopt->files)
  239.     {
  240.         LIST   *list = 0, *tmpList;
  241.         char    dir[_POSIX_PATH_MAX];
  242.         char    path[_POSIX_PATH_MAX];
  243.         char    base[_POSIX_PATH_MAX];
  244.         char   *rsp = 0;
  245.         int     count = 0;
  246.  
  247.         hash_foreach (user->con->uopt->files,
  248.               (hash_callback_t) create_file_list, &list);
  249.         dir[0] = 0;
  250.         if (results == 0)
  251.         results = 0x7fffffff;    /* hack, we really mean unlimited */
  252.         for (tmpList = list; tmpList && results;
  253.          tmpList = tmpList->next, results--)
  254.         {
  255.         DATUM  *d = tmpList->data;
  256.  
  257.         dirname (path, sizeof (path), d->filename);
  258.         my_basename (base, sizeof (base), d->filename);
  259.         if (count < 5 && dir[0] && !strcasecmp (dir, path))
  260.         {
  261.             /* same directory as previous result, append */
  262.             rsp = append_string (rsp, " \"%s\" %s %u %d %d %d", base,
  263. #if RESUME
  264.                      d->hash,
  265. #else
  266.                      "0",
  267. #endif
  268.                      d->size,
  269.                      BitRate[d->bitrate],
  270.                      SampleRate[d->frequency],
  271.                      d->duration);
  272.             if (!rsp)
  273.             break;
  274.             count++;
  275.         }
  276.         else
  277.         {
  278.             /* new directory */
  279.             strcpy (dir, path);
  280.             if (rsp)
  281.             {
  282.             /* send off the previous buffer command */
  283.             send_user (sender, MSG_SERVER_BROWSE_RESULT_NEW, "%s",
  284.                    rsp);
  285.             FREE (rsp);
  286.             }
  287.             rsp = append_string (0, "%s \"%s\" \"%s\" %s %u %d %d %d",
  288.                      user->nick, dir, base,
  289. #if RESUME
  290.                      d->hash,
  291. #else
  292.                      "0",
  293. #endif
  294.                      d->size,
  295.                      BitRate[d->bitrate],
  296.                      SampleRate[d->frequency],
  297.                      d->duration);
  298.             if (!rsp)
  299.             break;
  300.             count = 0;
  301.         }
  302.         }
  303.         list_free (list, 0);
  304.  
  305.         if (rsp)
  306.         {
  307.         send_user (sender, MSG_SERVER_BROWSE_RESULT_NEW, "%s", rsp);
  308.         FREE (rsp);
  309.         }
  310.     }
  311. #endif /* ! ROUTING_ONLY */
  312.     /* terminate the list */
  313.     send_user (sender, tag, "%s %u", user->nick,
  314.            /* don't give out ip if not sharing anything - security */
  315.            user->shared > 0 ? user->ip : 0);
  316.     }
  317.     else
  318.     {
  319.     /* relay the request to the server where this user is connected */
  320.     send_cmd (user->con, tag, ":%s %s %d", sender->nick, user->nick,
  321.           results);
  322.     }
  323. }
  324. #endif
  325.  
  326. /* 640 [:sender] nick
  327.  * direct browse request
  328.  */
  329. HANDLER (browse_direct)
  330. {
  331.     char   *sender_name, *nick;
  332.     USER   *sender, *user;
  333.  
  334.     (void) len;
  335.     if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
  336.     return;
  337.     nick = next_arg (&pkt);
  338.     if (!nick)
  339.     {
  340.     unparsable (con);
  341.     return;
  342.     }
  343.     user = hash_lookup (Users, nick);
  344.     if (!user)
  345.     {
  346.     nosuchuser (con);
  347.     return;
  348.     }
  349.  
  350.     if (ISUSER (con))
  351.     {
  352.     if (sender->port == 0 && user->port == 0)
  353.     {
  354.         send_cmd (con, MSG_SERVER_BROWSE_DIRECT_ERR,
  355.               "%s \"Both you and %s are firewalled; you cannot browse or download from them.\"",
  356.               user->nick, user->nick);
  357.         return;
  358.     }
  359.     else if (user->shared == 0)
  360.     {
  361.         send_cmd (con, MSG_SERVER_BROWSE_DIRECT_ERR,
  362.               "%s \"%s is not sharing any files.\"",
  363.               user->nick, user->nick);
  364.         return;
  365.     }
  366.     }
  367.  
  368.     if (ISUSER (user->con))
  369.     {
  370.     if (!is_ignoring (user->con->uopt->ignore, sender->nick))
  371.     {
  372.         if (user->port == 0)
  373.         {
  374.         /* client being browsed is firewalled.  send full info so
  375.          * a back connection to the browser can be made.
  376.          */
  377.         send_cmd (user->con, MSG_CLIENT_BROWSE_DIRECT, "%s %u %hu",
  378.             sender_name, sender->ip, sender->port);
  379.         }
  380.         else
  381.         {
  382.         /* directly connected to this server */
  383.         send_cmd (user->con, MSG_CLIENT_BROWSE_DIRECT, "%s",
  384.             sender_name);
  385.         }
  386.     }
  387.     else
  388.         send_cmd (con, MSG_SERVER_BROWSE_DIRECT_ERR,
  389.             "%s \"%s is not online.\"", user->nick, user->nick);
  390.     }
  391.     else
  392.     send_cmd (user->con, MSG_CLIENT_BROWSE_DIRECT, ":%s %s", sender_name,
  393.         user->nick);
  394. }
  395.  
  396. /* 641 [:sender] nick
  397.  * direct browse accept
  398.  */
  399. HANDLER (browse_direct_ok)
  400. {
  401.     char   *sender_name, *nick;
  402.     USER   *sender, *user;
  403.  
  404.     (void) len;
  405.     if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
  406.     return;
  407.     nick = next_arg (&pkt);
  408.     if (!nick)
  409.     {
  410.     unparsable (con);
  411.     return;
  412.     }
  413.     user = hash_lookup (Users, nick);
  414.     if (!user)
  415.     {
  416.     nosuchuser (con);
  417.     return;
  418.     }
  419.     if (ISUSER (user->con))
  420.     {
  421.     /* directly connected to this server */
  422.     send_cmd (user->con, MSG_SERVER_BROWSE_DIRECT_OK, "%s %u %hu",
  423.           sender->nick, sender->ip, sender->port);
  424.     }
  425.     else
  426.     send_cmd (user->con, MSG_SERVER_BROWSE_DIRECT_OK, ":%s %s",
  427.           sender_name, user->nick);
  428. }
  429.